using System;
using DomainMcpTypes = CKY.AgentPlatform.Domain.McpTools;
using AppMcpTypes = CKY.AgentPlatform.Application.Mcp;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Microsoft.Extensions.Logging;
using CKY.AgentPlatform.Application.Mcp;
using CKY.AgentPlatform.Domain.McpTools;

namespace CKY.AgentPlatform.Mcp
{
    /// <summary>
    /// MCP集成应用服务
    /// </summary>
    public class McpIntegrationAppService : ApplicationService, IMcpIntegrationAppService
    {
        private readonly CKY.AgentPlatform.Domain.McpTools.McpClientManager _mcpClientManager;
        private readonly IRepository<CKY.AgentPlatform.Domain.McpTools.McpTool, Guid> _mcpToolRepository;
        private readonly ILogger<McpIntegrationAppService> _logger;

        public McpIntegrationAppService(
            CKY.AgentPlatform.Domain.McpTools.McpClientManager mcpClientManager,
            IRepository<CKY.AgentPlatform.Domain.McpTools.McpTool, Guid> mcpToolRepository,
            ILogger<McpIntegrationAppService> logger)
        {
            _mcpClientManager = mcpClientManager;
            _mcpToolRepository = mcpToolRepository;
            _logger = logger;
        }

        /// <summary>
        /// 获取MCP客户端状态列表
        /// </summary>
        /// <returns>客户端状态列表</returns>
        public async Task<List<McpClientStatusDto>> GetClientStatusesAsync()
        {
            var statuses = _mcpClientManager.GetClientStatuses();
            return ObjectMapper.Map<List<DomainMcpTypes.McpClientStatus>, List<McpClientStatusDto>>(statuses);
        }

        /// <summary>
        /// 添加MCP服务器连接
        /// </summary>
        /// <param name="input">连接配置</param>
        /// <returns>操作结果</returns>
        public async Task<bool> AddServerAsync(AddMcpServerInput input)
        {
            try
            {
                var config = new DomainMcpTypes.McpClientConfig
                {
                    ServerUrl = input.ServerUrl,
                    ConnectTimeoutMs = input.ConnectTimeoutMs,
                    HeartbeatIntervalSeconds = input.HeartbeatIntervalSeconds,
                    MaxRetryCount = input.MaxRetryCount,
                    EnableDebugLog = input.EnableDebugLog,
                    Headers = input.Headers ?? new Dictionary<string, string>()
                };

                await _mcpClientManager.AddClientAsync(config);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to add MCP server: {ServerUrl}", input.ServerUrl);
                return false;
            }
        }

        /// <summary>
        /// 移除MCP服务器连接
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        /// <returns>操作结果</returns>
        public async Task<bool> RemoveServerAsync(string clientId)
        {
            try
            {
                await _mcpClientManager.RemoveClientAsync(clientId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to remove MCP client: {ClientId}", clientId);
                return false;
            }
        }

        /// <summary>
        /// 重启MCP服务器连接
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        /// <returns>操作结果</returns>
        public async Task<bool> RestartServerAsync(string clientId)
        {
            try
            {
                await _mcpClientManager.RestartClientAsync(clientId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to restart MCP client: {ClientId}", clientId);
                return false;
            }
        }

        /// <summary>
        /// 获取所有可用工具
        /// </summary>
        /// <returns>工具列表</returns>
        public async Task<List<McpToolDefinitionDto>> GetAvailableToolsAsync()
        {
            var tools = await _mcpClientManager.GetAllAvailableToolsAsync();
            return ObjectMapper.Map<List<DomainMcpTypes.McpToolDefinition>, List<McpToolDefinitionDto>>(tools);
        }

        /// <summary>
        /// 获取所有可用资源
        /// </summary>
        /// <returns>资源列表</returns>
        public async Task<List<McpResourceDefinitionDto>> GetAvailableResourcesAsync()
        {
            var resources = await _mcpClientManager.GetAllAvailableResourcesAsync();
            return ObjectMapper.Map<List<DomainMcpTypes.McpResourceDefinition>, List<McpResourceDefinitionDto>>(resources);
        }

        /// <summary>
        /// 调用工具
        /// </summary>
        /// <param name="input">工具调用参数</param>
        /// <returns>执行结果</returns>
        public async Task<McpToolExecutionResultDto> CallToolAsync(CallToolInput input)
        {
            var startTime = DateTime.UtcNow;
            
            try
            {
                var result = await _mcpClientManager.CallToolAsync(input.ToolName, input.Parameters);
                var executionTimeMs = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                
                _logger.LogInformation("工具执行成功: {ToolName}, 耗时: {ExecutionTimeMs}ms", input.ToolName, executionTimeMs);
                
                return new McpToolExecutionResultDto
                {
                    Success = true,
                    Result = result,
                    ExecutionTimeMs = executionTimeMs,
                    Timestamp = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                var executionTimeMs = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                _logger.LogError(ex, "工具执行失败: {ToolName}, 耗时: {ExecutionTimeMs}ms", input.ToolName, executionTimeMs);
                
                return new McpToolExecutionResultDto
                {
                    Success = false,
                    Error = ex.Message,
                    ExecutionTimeMs = executionTimeMs,
                    Timestamp = DateTime.UtcNow
                };
            }
        }

        /// <summary>
        /// 读取资源
        /// </summary>
        /// <param name="input">资源读取参数</param>
        /// <returns>资源内容</returns>
        public async Task<McpResourceReadResultDto> ReadResourceAsync(ReadResourceInput input)
        {
            try
            {
                var result = await _mcpClientManager.ReadResourceAsync(input.ResourceUri);
                
                return new McpResourceReadResultDto
                {
                    Success = true,
                    Content = result,
                    Timestamp = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to read resource: {ResourceUri}", input.ResourceUri);
                
                return new McpResourceReadResultDto
                {
                    Success = false,
                    Error = ex.Message,
                    Timestamp = DateTime.UtcNow
                };
            }
        }

        /// <summary>
        /// 测试MCP服务器连接
        /// </summary>
        /// <param name="input">测试连接参数</param>
        /// <returns>测试结果</returns>
        public async Task<McpConnectionTestResultDto> TestConnectionAsync(TestConnectionInput input)
        {
            try
            {
                var config = new DomainMcpTypes.McpClientConfig
                {
                    ServerUrl = input.ServerUrl,
                    ConnectTimeoutMs = 10000, // 测试连接使用较短超时
                    EnableDebugLog = false
                };

                var client = new McpClient(config);
                await client.ConnectAsync();

                // 检查是否成功获取工具列表
                var tools = client.GetAvailableTools();

                await client.DisconnectAsync();

                return new McpConnectionTestResultDto
                {
                    Success = true,
                    ServerUrl = input.ServerUrl,
                    ToolCount = tools.Count,
                    Message = "Connection successful",
                    Timestamp = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                return new McpConnectionTestResultDto
                {
                    Success = false,
                    ServerUrl = input.ServerUrl,
                    Message = ex.Message,
                    Timestamp = DateTime.UtcNow
                };
            }
        }

        /// <summary>
        /// 同步MCP工具到数据库
        /// </summary>
        /// <returns>同步结果</returns>
        public async Task<McpSyncResultDto> SyncToolsAsync()
        {
            try
            {
                var tools = await _mcpClientManager.GetAllAvailableToolsAsync();
                var syncCount = 0;

                foreach (var tool in tools)
                {
                    try
                    {
                        var existingTool = await _mcpToolRepository.FirstOrDefaultAsync(t => t.Name == tool.Name);
                        
                        if (existingTool == null)
                        {
                            var newTool = new DomainMcpTypes.McpTool(
                                GuidGenerator.Create(),
                                tool.Name,
                                tool.Description,
                                DomainMcpTypes.McpToolType.Custom,
                                System.Text.Json.JsonSerializer.Serialize(tool.Configuration))
                            {
                                Configuration = System.Text.Json.JsonSerializer.Serialize(tool.InputSchema),
                                Parameters = System.Text.Json.JsonSerializer.Serialize(tool.InputSchema),
                                IsActive = true,
                                Tags = "mcp,auto-sync",
                                Author = "MCP Server",
                                TimeoutSeconds = 30,
                                MaxRetries = 3
                            };

                            await _mcpToolRepository.InsertAsync(newTool);
                            syncCount++;
                        }
                        else
                        {
                            existingTool.Description = tool.Description;
                            existingTool.Configuration = System.Text.Json.JsonSerializer.Serialize(tool.Configuration);
                            existingTool.Parameters = System.Text.Json.JsonSerializer.Serialize(tool.InputSchema);
                            existingTool.IsActive = true;

                            await _mcpToolRepository.UpdateAsync(existingTool);
                            syncCount++;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "Failed to sync tool: {ToolName}", tool.Name);
                    }
                }

                return new McpSyncResultDto
                {
                    Success = true,
                    TotalTools = tools.Count,
                    SyncedTools = syncCount,
                    Message = $"Successfully synced {syncCount} tools",
                    Timestamp = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to sync MCP tools");
                
                return new McpSyncResultDto
                {
                    Success = false,
                    Message = ex.Message,
                    Timestamp = DateTime.UtcNow
                };
            }
        }

        /// <summary>
        /// 获取MCP连接统计信息
        /// </summary>
        /// <returns>统计信息</returns>
        public async Task<McpStatisticsDto> GetStatisticsAsync()
        {
            var statuses = _mcpClientManager.GetClientStatuses();
            var tools = await _mcpClientManager.GetAllAvailableToolsAsync();
            var resources = await _mcpClientManager.GetAllAvailableResourcesAsync();

            return new McpStatisticsDto
            {
                TotalServers = statuses.Count,
                ConnectedServers = statuses.Count(s => s.IsConnected),
                TotalTools = tools.Count,
                TotalResources = resources.Count,
                AverageResponseTime = 0, // TODO: 实际计算平均响应时间
                Timestamp = DateTime.UtcNow
            };
        }
    }

    /// <summary>
    /// MCP集成应用服务接口
    /// </summary>
    public interface IMcpIntegrationAppService : IApplicationService
    {
        Task<List<McpClientStatusDto>> GetClientStatusesAsync();
        Task<bool> AddServerAsync(AddMcpServerInput input);
        Task<bool> RemoveServerAsync(string clientId);
        Task<bool> RestartServerAsync(string clientId);
        Task<List<McpToolDefinitionDto>> GetAvailableToolsAsync();
        Task<List<McpResourceDefinitionDto>> GetAvailableResourcesAsync();
        Task<McpToolExecutionResultDto> CallToolAsync(CallToolInput input);
        Task<McpResourceReadResultDto> ReadResourceAsync(ReadResourceInput input);
        Task<McpConnectionTestResultDto> TestConnectionAsync(TestConnectionInput input);
        Task<McpSyncResultDto> SyncToolsAsync();
        Task<McpStatisticsDto> GetStatisticsAsync();
    }

    // DTO定义
    public class McpClientStatusDto
    {
        public string ClientId { get; set; }
        public string ServerUrl { get; set; }
        public bool IsConnected { get; set; }
        public int ToolCount { get; set; }
        public int ResourceCount { get; set; }
    }

    public class McpToolDefinitionDto
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public object InputSchema { get; set; }
        public Dictionary<string, object> Configuration { get; set; }
    }

    public class McpResourceDefinitionDto
    {
        public string Uri { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string MimeType { get; set; }
    }

    public class AddMcpServerInput
    {
        public string ServerUrl { get; set; }
        public int ConnectTimeoutMs { get; set; } = 30000;
        public int HeartbeatIntervalSeconds { get; set; } = 30;
        public int MaxRetryCount { get; set; } = 3;
        public bool EnableDebugLog { get; set; } = false;
        public Dictionary<string, string> Headers { get; set; }
    }

    public class CallToolInput
    {
        public string ToolName { get; set; }
        public object Parameters { get; set; }
    }

    public class McpToolExecutionResultDto
    {
        public bool Success { get; set; }
        public object Result { get; set; }
        public string Error { get; set; }
        public int ExecutionTimeMs { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public class ReadResourceInput
    {
        public string ResourceUri { get; set; }
    }

    public class McpResourceReadResultDto
    {
        public bool Success { get; set; }
        public object Content { get; set; }
        public string Error { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public class TestConnectionInput
    {
        public string ServerUrl { get; set; }
    }

    public class McpConnectionTestResultDto
    {
        public bool Success { get; set; }
        public string ServerUrl { get; set; }
        public int ToolCount { get; set; }
        public int ResourceCount { get; set; }
        public string Message { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public class McpSyncResultDto
    {
        public bool Success { get; set; }
        public int TotalTools { get; set; }
        public int SyncedTools { get; set; }
        public string Message { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public class McpStatisticsDto
    {
        public int TotalServers { get; set; }
        public int ConnectedServers { get; set; }
        public int TotalTools { get; set; }
        public int TotalResources { get; set; }
        public double AverageResponseTime { get; set; }
        public DateTime Timestamp { get; set; }
    }
}